#include <config.h>
#include <utils.h>
#include <os.h>
#include <device.h>
#include <printk.h>
#include <settings.h>
#include <syserr.h>
#include "board.h"
#include "encode.h"
#include "dev.h"
#include "dev_show.h"
#include "auto_report.h"
#include "smart_sensor.h"
#include "mbus_smart.h"

#ifdef configUSING_MBUS

static device_t *serial_mbus;
tcb_t mbus_tcb;
uint8_t g_frame_buf[1024];
static int check_smart_mbus_frame(uint8_t *data, size_t len)
{
	int frame_len = 0;
	smart_frame_t *pframe = get_smart_frame(data, len);
    if (!pframe) return 0;//illegal frame

    frame_len = smart_frame_len(pframe);

#ifdef  MBUS_SMART_DEBUG
    log_d("got smart frame:\n");
    log_arr_d((uint8_t *)pframe, len);
#endif
	device_ctrl(dev_led,STATE_LED_FLASH_3,NULL);
    
	/********proto_handler****************/
	int ret = smart_frame_handle(pframe);
    if (ret > 0)
    {
		device_ctrl(dev_led,STATE_LED_FLASH_3,NULL);
        device_write(serial_mbus, 0, pframe, ret);
    }
	
	frame_len += (uint8_t *)pframe - data;
    return frame_len;//frame_len + data_len befor frame 
}

static void do_mbus_data(void)
{
	int len = device_peek(serial_mbus, 0, g_frame_buf, sizeof(g_frame_buf));
    if (len)
    {
       int ret = check_smart_mbus_frame(g_frame_buf,len);
	   if(ret)
	   {
			 device_read(serial_mbus, 0, g_frame_buf, ret);//clear extra data befor frame and frame data
		     if(len >ret)
				  task_send_signal(&mbus_tcb, SIG_DATA);//do extra data after frame
	   }
	   else
	   {
		   if(len>0xff)
			   device_read(serial_mbus, 0, g_frame_buf, len);//clear solt
	   }
    }
}

static err_t serial_mbus_open(void)
{
	err_t err;
    struct serial_configure cfg;

    serial_mbus = device_find("mbus");
    assert(serial_mbus);

    err = device_ctrl(serial_mbus, SERIAL_CTRL_GETCFG, &cfg);
    if (err != 0) return err;

    cfg.baud_rate = BAUD_RATE_9600;//;BAUD_RATE_2400
    cfg.bufsz     = SIZE_512B;//rx_slot = tx_slot = 512B
    cfg.data_bits = DATA_BITS_8;
    cfg.parity    = PARITY_NONE;
    cfg.stop_bits = STOP_BITS_1;
    err = device_ctrl(serial_mbus, SERIAL_CTRL_SETCFG, &cfg);
    if (err != 0) return err;

    err = device_open(serial_mbus, DEVICE_FLAG_INT_RX | DEVICE_FLAG_INT_TX | DEVICE_FLAG_FASYNC);
    if (err != 0) return err;

    return 0;
}

static void mbus_task_cb(struct task_ctrl_blk *tcb, ubase_t data)
{
    tSTART(tcb);
	
    serial_mbus_open();
	
    for (;;)
    {
        task_wait_signal(tcb);
        sig_t sig = task_signal(tcb);
		if(sigget(sig, SIG_DATA))
		{
			do_mbus_data();
		}
    }
    tEND();
}

void mbus_init(void)
{
    task_create(&mbus_tcb, mbus_task_cb, 0);
}

#endif
